package com.ruoyi.schedule.service.impl;

import com.ruoyi.schedule.domain.Rule;
import com.ruoyi.schedule.domain.SchedulePlan;
import com.ruoyi.schedule.domain.Shift;
import com.ruoyi.schedule.service.IScheduleAlgorithmService;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

@Service
public class ScheduleAlgorithmServiceImpl implements IScheduleAlgorithmService {
    
    @Override
    public Map<Long, List<Shift>> generateSchedule(SchedulePlan plan, List<Rule> rules, List<Shift> shifts) {
        // 1. 根据规则对班次进行排序
        shifts.sort((s1, s2) -> s1.getStartTime().compareTo(s2.getStartTime()));
        
        // 2. 初始化排班结果
        Map<Long, List<Shift>> scheduleResult = new HashMap<>();
        
        // 3. 实现智能分配算法
        Map<Long, Integer> employeeWorkHours = new HashMap<>();
        Map<Long, Integer> consecutiveWorkDays = new HashMap<>();
        
        // 初始化员工工作时长统计
        plan.getEmployeeIds().forEach(id -> {
            employeeWorkHours.put(id, 0);
            consecutiveWorkDays.put(id, 0);
        });
        
        // 按员工偏好、工作强度平衡和特殊日期处理分配班次
        for (Shift shift : shifts) {
            Long bestEmployee = null;
            int minScore = Integer.MAX_VALUE;
            
            // 检查是否为特殊日期(周末/节假日)
            boolean isSpecialDay = isSpecialDay(shift.getDate());
            
            // 寻找最适合当前班次的员工
            for (Long employeeId : plan.getEmployeeIds()) {
                int currentHours = employeeWorkHours.get(employeeId);
                int consecutiveDays = consecutiveWorkDays.get(employeeId);
                
                // 计算员工得分(工作时长+连续工作天数惩罚)
                int score = currentHours * 2 + consecutiveDays * 5;
                
                // 特殊日期额外惩罚
                if (isSpecialDay) {
                    score += 10;
                }
                
                // 优先选择得分最低且符合偏好的员工
                if (score < minScore && 
                    (shift.getPreferredEmployeeIds() == null || 
                     shift.getPreferredEmployeeIds().contains(employeeId))) {
                    minScore = score;
                    bestEmployee = employeeId;
                }
            }
            
            // 如果没有符合偏好的员工，选择得分最低的
            if (bestEmployee == null) {
                for (Long employeeId : plan.getEmployeeIds()) {
                    int currentHours = employeeWorkHours.get(employeeId);
                    int consecutiveDays = consecutiveWorkDays.get(employeeId);
                    int score = currentHours * 2 + consecutiveDays * 5;
                    
                    if (score < minScore) {
                        minScore = score;
                        bestEmployee = employeeId;
                    }
                }
            }
            
            // 分配班次并更新统计
            if (bestEmployee != null) {
                scheduleResult.computeIfAbsent(bestEmployee, k -> new ArrayList<>()).add(shift);
                employeeWorkHours.put(bestEmployee, employeeWorkHours.get(bestEmployee) + shift.getDurationHours());
                
                // 更新连续工作天数
                if (shift.getDurationHours() > 0) {
                    consecutiveWorkDays.put(bestEmployee, consecutiveWorkDays.get(bestEmployee) + 1);
                } else {
                    consecutiveWorkDays.put(bestEmployee, 0);
                }
            }
        }
        
        return scheduleResult;
    }

    @Override
    public boolean validateRules(List<Rule> rules) {
        if (rules == null || rules.isEmpty()) {
            return false;
        }
        
        // 验证规则是否冲突
        for (int i = 0; i < rules.size(); i++) {
            for (int j = i + 1; j < rules.size(); j++) {
                if (rules.get(i).conflictsWith(rules.get(j))) {
                    return false;
                }
            }
        }
        
        return true;
    }
}